<script lang="tsx">
import { computed, defineComponent, ref, unref } from 'vue'
import type { BasicColumn, BasicTableProps, SizeType, TableActionType } from './types/table'
import { useVxeDataSource } from './hooks/useDataSource'
import type { EmitType, Recordable } from '@/types/global'
import { useVxePagination } from './hooks/usePagination'
import { useVxeLoading } from './hooks/useLoading'
import { BasicForm, useForm } from '@/components/BasicForm'
import { PAGE_SIZE } from './const'
import { isObject } from 'lodash-es'
import { type PaginationProps, ElEmpty } from 'element-plus'
import { setIndex, useVxeColumns } from './hooks/useColumns'
import { getSlot } from '@/components/BasicForm/src/common/helper'
import VxeTablePagination from './components/TablePagination.vue'
import { VxeTable, VxeColumn } from 'vxe-table'
import VxeTableColumn from './components/TableColumn.vue'
import { useVxeMethods } from './hooks/useVxeMethods'
import { basicProps } from './props'
import { useVxeTableForm } from './hooks/useTableForm'
import { deepMerge } from '@/utils/gloab'

export default defineComponent({
  name: 'BasicTable',
  emits: ['register', 'fetch-success', 'fetch-error'],
  props: basicProps,
  setup(props, { attrs, slots, emit, expose }) {
    const innerPropsRef = ref<Partial<BasicTableProps>>()
    const tableData = ref<Recordable[]>([])
    const vxeTableRef = ref(null)
    const getProps = computed(() => {
      // 合并props和attrs
      let data = deepMerge(props, unref(innerPropsRef))
      return {
        ...attrs,
        ...data,
      } as unknown as BasicTableProps
    })
    const getVxeTableRef = computed(() => {
      return vxeTableRef.value
    })
    // 表格所有参数
    const getBindValues = computed(() => {
      const data = unref(getDataSourceRef) || []

      let propsData: Recordable = {
        ...unref(seqConfigComp),
        ...attrs,
        ...unref(getProps),
        data,
        loading: getLoading.value,
      }

      // console.log('propsData', propsData);
      return propsData
    })
    // 序号
    const seqConfigComp = computed(() => {
      const { showIndexColumn, startIndex, reserveIndex } = unref(getProps)
      if (showIndexColumn) {
        let pageSize = PAGE_SIZE
        let currentPage = 1
        if (isObject(unref(getPaginationInfo))) {
          pageSize = (unref(getPaginationInfo) as PaginationProps).pageSize || PAGE_SIZE
          currentPage = (unref(getPaginationInfo) as PaginationProps).currentPage || 1
        }
        let seqConfig = {
          startIndex: reserveIndex
            ? setIndex(reserveIndex, startIndex || 0, pageSize, currentPage)
            : startIndex,
        }
        return { seqConfig }
      } else {
        return null
      }
    })
    // 是否占满全部
    const canResizeClass = computed(() => {
      let className = {
        body: '',
        table: '',
      }
      if (getBindValues.value.canResize) {
        className.body = 'flex  absolute left-0 top-0 bottom-0 right-0'
        className.table = 'flex-1 w-[100%] relative'
      } else {
        className.body = ''
        className.table = ''
      }
      return className
    })
    const { getColumnsRef } = useVxeColumns(getProps)

    const [registerForm, formActions] = useForm()
    useVxeMethods(getVxeTableRef)

    const { getLoading, setLoading } = useVxeLoading(getProps)

    const { getPaginationInfo, setPagination, setShowPagination, getShowPagination } =
      useVxePagination(getProps)

    const {
      getDataSourceRef,
      getDataSource,
      getRawDataSource,
      setTableData,
      fetch,
      reload,
      deleteSelectRowByKey,
      insertTableDataRecord,
      updateTableDataRecord,
    } = useVxeDataSource(
      getProps,
      {
        tableData,
        getPaginationInfo,
        setLoading,
        setPagination,
        getFieldsValue: formActions.getFieldsValue,
      },
      emit as EmitType,
    )
    const {
      getFormProps,
      getShowForm,
      setShowForm,
      getActionColumn,
      getTableSlotKeys,
      replaceTableSlotKey,
      getFormSlotKeys,
      replaceFormSlotKey,
      handleSearchInfoChange,
    } = useVxeTableForm(getProps, slots, fetch, getLoading)

    function setProps(props: Partial<BasicTableProps>) {
      innerPropsRef.value = { ...unref(innerPropsRef), ...props }
    }
    const tableAction: TableActionType = {
      reload,
      getSize: () => {
        return unref(getBindValues).size as SizeType
      },
      setProps,
      setShowForm,
      getShowForm,
      getDataSource,
      getRawDataSource,
      setTableData,
      setShowPagination,
      getShowPagination,
      getPagination: () => {
        return getPaginationInfo.value
      },
      setPagination,
      getVxeTableRef: () => {
        return getVxeTableRef.value
      },
      getLoading: () => {
        return unref(getLoading) || false
      },
      setLoading,
      deleteSelectRowByKey,
      insertTableDataRecord,
      updateTableDataRecord,
      // setPagination,
      // setTableData,
      // setSelectedRowKeys,
      // setColumns,
      // setLoading,
      // getDataSource,
      // getRawDataSource,

      // getRowSelection,
      // getPaginationRef: getPagination,
      // getColumns,
      // getCacheColumns,
      // emit,
      // updateTableData,
      // setShowPagination,
      // getShowPagination,
      // setCacheColumnsByField,
      // expandAll,
      // expandRows,
      // collapseAll,
      // scrollTo,

      // setCacheColumns,
      // setShowForm,
      // getShowForm
    }

    function RenderForm() {
      console.log('RenderForm')

      let show = getShowForm() && unref(getBindValues).useSearchForm
      let formslots: any = {}

      unref(getFormSlotKeys).forEach((e) => {
        formslots[replaceFormSlotKey(e)] = (data: any) => getSlot(slots, e, data)
      })
      // console.log('getFormProps', getFormProps);

      return (
        <>
          {show ? (
            <BasicForm
              submitOnReset
              {...unref(getFormProps)}
              onRegister={registerForm}
              onSubmit={handleSearchInfoChange}
              v-slots={formslots}
            ></BasicForm>
          ) : null}
        </>
      )
    }
    function RenderTable() {
      let tableSlot: any = {}
      unref(getTableSlotKeys).forEach((e) => {
        tableSlot[replaceTableSlotKey(e)] = (data: any) => getSlot(slots, e, data)
      })
      let tableBodySlot = slots.tableBody ? (
        getSlot(slots, 'tableBody', { ...unref(getBindValues), getColumnsRef })
      ) : (
        <VxeTableColumn
          getColumnsRef={unref(getColumnsRef)}
          getTableProps={unref(getProps)}
          getPaginationInfo={unref(getPaginationInfo)}
          setProps={setProps}
          v-slots={tableSlot}
        />
      )
      let actionSlot = slots.action
        ? { default: (data: any) => getSlot(slots, 'action', data) }
        : null

      let acton = null

      if (isObject(unref(getActionColumn))) {
        const field =
          (unref(getActionColumn) as BasicColumn).dataIndex ||
          (unref(getActionColumn) as BasicColumn).field
        acton = (
          <VxeColumn
            {...unref(getActionColumn)}
            title={(unref(getActionColumn) as BasicColumn).title || '操作'}
            field={field}
            v-slots={actionSlot}
          />
        )
      }

      let tableSlots: Recordable = {
        empty: () => (slots.empty ? getSlot(slots, 'empty') : <ElEmpty></ElEmpty>),
      }
      if (slots.tableLoading) {
        tableSlots['loading'] = getSlot(slots, 'tableLoading')
      }

      // 删除高度
      if (unref(getBindValues).canResize == false) {
        delete unref(getBindValues).height
      }

      return (
        <>
          {
            <VxeTable {...unref(getBindValues)} ref={vxeTableRef} v-slots={tableSlots}>
              {tableBodySlot}
              {acton}
            </VxeTable>
          }
        </>
      )
    }
    function RenderPagination() {
      let totalslot = slots.totalSlot ? { totalSlot: () => getSlot(slots, 'totalSlot') } : null
      return (
        <>
          {slots.pagination ? (
            getSlot(slots, 'pagination', getPaginationInfo)
          ) : (
            <VxeTablePagination
              getPaginationInfo={unref(getPaginationInfo)}
              fetch={fetch}
              setPagination={setPagination}
              v-slots={totalslot}
            ></VxeTablePagination>
          )}
        </>
      )
    }

    emit('register', tableAction, formActions)
    expose({ getVxeTableRef })

    return () => {
      return (
        <div class="flex flex-col w-[100%] h-[100%]">
          {RenderForm()}
          {slots.body ? getSlot(slots, 'body') : null}
          <div class="relative w-[100%] h-[100%]">
            <div class={[unref(canResizeClass).body]}>
              {slots.left ? getSlot(slots, 'left') : null}
              <div class="w-[100%] flex flex-col flex-1">
                <div class={[unref(canResizeClass).table]}>{RenderTable()}</div>
                {RenderPagination()}
              </div>
            </div>
          </div>
        </div>
      )
    }
  },
})
</script>
<style lang="scss" scoped></style>
